package com.sgl.gk.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sg.comm.common.Ret;
import com.sg.comm.opcuav2.NodeDTOV2;
import com.sg.comm.opcuav2.OpcUaWriteReqV2;
import com.sg.comm.service.OpcUaServiceV2;
import com.sgl.common.core.domain.AjaxResult;
import com.sgl.gk.controller.vo.GkProductionLineVo;
import com.sgl.gk.controller.vo.GkStationConfigurationVo;
import com.sgl.gk.controller.vo.GkStationVo;
import com.sgl.gk.domain.*;
import com.sgl.gk.domain.plc.Node;
import com.sgl.gk.domain.plc.OpcUa;
import com.sgl.gk.domain.plc.OpcUaList;
import com.sgl.gk.mapper.*;
import com.sgl.gk.service.GkStationEventService;
import com.sgl.gk.tools.ReadOpcUaNodeInfoTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author:xec
 * @date:2022/10/31 18:50
 **/
@Service
@Slf4j
public class GkStationEventServiceImpl implements GkStationEventService {
    @Autowired
    GkStationEventMapper gkStationEventMapper;

    @Autowired
    GkStationMapper gkStationMapper;

    @Autowired
    GkStationConfigurationMapper gkStationConfigurationMapper;

    @Autowired
    GkSignalCommunicationMapper gkSignalCommunicationMapper;

    @Autowired
    GkProductionLineMapper gkProductionLineMapper;

    @Override
    public AjaxResult list(GkStationEvent gkStationEvent) {
        List<GkStationEvent> list = gkStationEventMapper.list(gkStationEvent);
        List<GkStationVo> gkStationVos = gkStationMapper.list(null);
        for (GkStationEvent stationEvent : list) {
            String[] split = stationEvent.getConditionStationId().trim().split(",");
            ArrayList arrayList = new ArrayList();
            for (String s : split) {
                if (!StringUtils.isEmpty(s)) {
                    for (GkStationVo gkStationVo : gkStationVos) {
                        if (gkStationVo.getId().equals(Long.parseLong(s))) {
                            arrayList.add(gkStationVo.getName());
                        }
                    }
                }
            }
            stationEvent.setConditionStationNames(StringUtils.join(arrayList,","));
        }
        return AjaxResult.success(list);
    }
    @Override
    public AjaxResult add(GkStationEvent gkStationEvents){
        if (com.sgl.common.utils.StringUtils.isEmpty(gkStationEvents.getConditionStationId())||gkStationEvents.getConditionConfigurationId()==null||com.sgl.common.utils.StringUtils.isEmpty(gkStationEvents.getValue())||gkStationEvents.getConfigurationId()==null){
            return AjaxResult.error("事件参数必须填写");
        }
        gkStationEventMapper.add(gkStationEvents);
        saveEventsToFile();
        return AjaxResult.success();
    }

    @Override
    public AjaxResult save(GkStationEvent[] gkStationEvents) {
        // todo 事件保存按钮与OPCUA后端通讯
        return AjaxResult.success("保存成功");
    }


    @Transactional
    @Override
    public AjaxResult edit(GkStationEvent gkStationEvents) {
        int row = gkStationEventMapper.edit(gkStationEvents);
        saveEventsToFile();
        return AjaxResult.success();
    }

    @Override
    public AjaxResult removeByIds(Long[] ids) {
        int row = gkStationEventMapper.removeByIds(ids);
        if (row>0){
            saveEventsToFile();
            return AjaxResult.success("删除成功");
        }
        return AjaxResult.error("删除失败");
    }

    /**
     * 保存事件信息到文件
     */
    private void saveEventsToFile(){
        List<GkStationEvent> list = gkStationEventMapper.list(null);
        // 过滤掉需要扫码的事件
        list = list.stream().filter(gkStationEvent -> gkStationEvent.getConditionValue().equals("16")).collect(Collectors.toList());

        // 需要写入文件的变量信息
        List<Long> requestConfigIds = list.stream().map(GkStationEvent::getConditionConfigurationId).distinct().collect(Collectors.toList());
        List<Long> replyConfigIds = list.stream().map(GkStationEvent::getConfigurationId).collect(Collectors.toList());

        List<Long> configIds = new ArrayList<>();
        configIds.addAll(requestConfigIds);
        configIds.addAll(replyConfigIds);

        // 获取到需要写入和保存的data变量信息
        List<GkStationConfiguration> gkStationConfigurationList = new ArrayList<>();
        if (CollUtil.isNotEmpty(configIds)) {
            gkStationConfigurationList = gkStationConfigurationMapper.selectInfoByIds(configIds);
        }else {
            return;
        }

        List<Long> stationIds = list.stream().map(GkStationEvent::getStationId).distinct().collect(Collectors.toList());
        Map<Long, List<GkStationEvent>> stationEventMap = list.parallelStream().collect(Collectors.groupingBy(GkStationEvent::getStationId));
        if (CollUtil.isNotEmpty(stationIds)){
            List<GkStation> gkStationList = gkStationMapper.selectInfosByIds(stationIds);

            List<Long> signalIds = gkStationList.stream().map(GkStation::getSignalCommunicationId).collect(Collectors.toList());
            List<GkSignalCommunication> gkSignalCommunicationList = gkSignalCommunicationMapper.selectInfoByIds(signalIds);

            Map<Long, List<GkStation>> signalStationMap = gkStationList.parallelStream().collect(Collectors.groupingBy(GkStation::getSignalCommunicationId));

            OpcUaList opcUaList = new OpcUaList();
            List<OpcUa> uaList = new ArrayList<>();
            OpcUaList getOpcUaList = ReadOpcUaNodeInfoTool.GetOpcUaList();
            List<OpcUa> opcUas = getOpcUaList.getOpcUaList();
            for (GkSignalCommunication gkSignalCommunication : gkSignalCommunicationList) {
                OpcUa opcUa = new OpcUa();
                opcUa.setUid(gkSignalCommunication.getCommunicationProtocol());
                List<Node> fileNodeList = new ArrayList<>();
                for (OpcUa opcUa1 : opcUas) {
                    if (gkSignalCommunication.getCommunicationProtocol().equals(opcUa1.getUid())){
                        opcUa.setUid(opcUa1.getUid());
                        opcUa.setEnable(opcUa1.getEnable());
                        opcUa.setEndpointUrl(opcUa1.getEndpointUrl());
                        opcUa.setNameSpace(opcUa1.getNameSpace());
                        opcUa.setPeriod(opcUa1.getPeriod());
                        fileNodeList = opcUa1.getNodeList();
                        break;
                    }
                }
                ArrayList<Node> nodeList = new ArrayList<>();
                List<GkStation> gkStations = signalStationMap.get(gkSignalCommunication.getId().longValue());
                if (CollUtil.isNotEmpty(gkStations)){
                    for (GkStation gkStation : gkStations) {
                        List<GkStationEvent> gkStationEventList = stationEventMap.get(gkStation.getId().longValue());
                        if (CollUtil.isNotEmpty(gkStationEventList)){
                            List<GkProductionLineVo> gkProductionLineVos = gkProductionLineMapper.selectInfoByIds(Collections.singletonList(gkStation.getProductionLineId()));
                            for (GkStationEvent gkStationEvent : gkStationEventList) {
                                Node node1 = new Node();
                                for (GkStationConfiguration gkStationConfiguration : gkStationConfigurationList) {
                                    // 找到Request_data
                                    if (gkStationConfiguration.getId().longValue()==gkStationEvent.getConditionConfigurationId().longValue()) {
                                        String nodeName = "data_pc_plc.plc_request."+gkStationConfiguration.getVariableName();
                                        for (Node node : fileNodeList) {
                                            if (node.getDisplayName().equals(nodeName)) {
                                                node1.setNodeId(node.getNodeId());
                                                node1.setNodeName(node.getNodeName());
                                                node1.setNodeValue(gkStationEvent.getConditionValue());
                                                node1.setNodeType(node.getNodeType());
                                                node1.setDisplayName(nodeName);
                                                break;
                                            }
                                        }
                                    }
                                    // 找到Replay_data
                                    if (gkStationConfiguration.getId().longValue()==gkStationEvent.getConditionConfigurationId().longValue()) {
                                        String nodeName = "data_pc_plc.pc_reply."+gkStationConfiguration.getVariableName();
                                        for (Node node : fileNodeList) {
                                            if (node.getDisplayName().equals(nodeName)) {
                                                ArrayList<Node> writeNodeList = new ArrayList<>();
                                                Node node2 = new Node();
                                                node2.setNodeId(node.getNodeId());
                                                node2.setNodeName(node.getNodeName());
                                                node2.setNodeValue(gkStationEvent.getValue());
                                                node2.setNodeType(node.getNodeType());
                                                node2.setDisplayName(nodeName);
                                                writeNodeList.add(node2);
                                                node1.setWriteNodeList(writeNodeList);
                                                break;
                                            }
                                        }
                                    }
                                }

                                List<Node> saveNodeList = new ArrayList<>();
                                String[] split = gkStationEvent.getConditionStationId().split(",");
                                // 需要读取的工位id
                                List<Long> saveOrScanningStationIds = new ArrayList<>();
                                for (String s : split) {
                                    saveOrScanningStationIds.add(Long.parseLong(s));
                                }

                                saveNodeList = GetSaveNodeList(gkProductionLineVos,gkStationEvent,saveOrScanningStationIds, gkSignalCommunication);
                                if (CollUtil.isNotEmpty(saveNodeList)) {
                                    node1.setSaveNodeList(saveNodeList);
                                }
                                nodeList.add(node1);
                            }
                        }
                    }
                }
                opcUa.setNodeList(nodeList);
                uaList.add(opcUa);
            }
            opcUaList.setOpcUaList(uaList);
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File("D:/sg/jdk/bin/config/dev/opc-ua.json"),opcUaList);
//                objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File("./opc-ua.json"),opcUaList);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    private List<Node> GetSaveNodeList(List<GkProductionLineVo> gkProductionLineVos, GkStationEvent gkStationEvent,
                                       List<Long> saveOrScanningStationIds, GkSignalCommunication gkSignalCommunication){
        List<Node> nodes = new ArrayList<>();
        OpcUaList opcUaList = ReadOpcUaNodeInfoTool.GetOpcUaList();
        List<OpcUa> uaList = opcUaList.getOpcUaList();
        List<Node> fileNodeList = new ArrayList<>();
        for (OpcUa opcUa : uaList) {
            if (opcUa.getUid().equals(gkSignalCommunication.getCommunicationProtocol())) {
                fileNodeList = opcUa.getNodeList();
            }
        }
        List<GkStation> saveStationInfos = gkStationMapper.selectInfosByIds(saveOrScanningStationIds);
        List<GkStationConfigurationVo> saveConfigurationInfos = gkStationConfigurationMapper.selectInfoByType2StationIds(saveOrScanningStationIds);
        Map<Long, List<GkStationConfigurationVo>> saveConfigurationInfoMap = saveConfigurationInfos.parallelStream().collect(Collectors.groupingBy(GkStationConfigurationVo::getStationId));

        for (GkStation saveStationInfo : saveStationInfos) {
            if (saveStationInfo.getSignalCommunicationId() != null) {
                if (saveStationInfo.getSignalCommunicationId().longValue() == gkSignalCommunication.getId().longValue()) {
                    if (CollUtil.isEmpty(saveConfigurationInfoMap)){
                        continue;
                    }
                    List<GkStationConfigurationVo> saveConfigurationInfoList = saveConfigurationInfoMap.get(saveStationInfo.getId());
                    if (CollUtil.isEmpty(saveConfigurationInfoList)){
                        continue;
                    }
                    for (GkStationConfigurationVo gkStationConfigurationVo : saveConfigurationInfoList) {
                        String nodeName = "";
                        for (GkProductionLineVo gkProductionLineVo : gkProductionLineVos) {
                            if (gkProductionLineVo.getId().longValue() == saveStationInfo.getProductionLineId().longValue()) {
                                // 配置数据源。因为总成装配线的OP110等数据在Data里面拿取数据
                                // 事件数据源的读取
                                if (StringUtils.isNotEmpty(gkStationEvent.getDataSource())) {
                                    nodeName = gkStationEvent.getDataSource() + "." + ((saveStationInfo.getCode() == null || saveStationInfo.getCode().equals("")) ? saveStationInfo.getCode() : (saveStationInfo.getCode() + ".")) + gkStationConfigurationVo.getVariableName();
                                } else if (!StringUtils.isEmpty(saveStationInfo.getDataSource())) {
                                    nodeName = saveStationInfo.getDataSource() + "." + ((saveStationInfo.getCode() == null || saveStationInfo.getCode().equals("")) ? saveStationInfo.getCode() : (saveStationInfo.getCode() + ".")) + gkStationConfigurationVo.getVariableName();
                                } else {
                                    nodeName = gkProductionLineVo.getCode() + "." + ((saveStationInfo.getCode() == null || saveStationInfo.getCode().equals("")) ? saveStationInfo.getCode() : (saveStationInfo.getCode() + ".")) + gkStationConfigurationVo.getVariableName();
                                }
                            }
                        }
                        if (CollUtil.isNotEmpty(fileNodeList)){
                            for (Node node : fileNodeList) {
                                if (node.getDisplayName().equals(nodeName)) {
                                    Node node1 = new Node();
                                    node1.setNodeId(node.getNodeId());
                                    node1.setNodeName(nodeName);
                                    node1.setNodeType(node.getNodeType());
                                    node1.setDisplayName(node.getDisplayName());
                                    nodes.add(node1);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        for (Node node : fileNodeList) {
            if (node.getDisplayName().equals("DB_RECIPE.ProductType")) {
                nodes.add(node);
            }
            if (node.getDisplayName().equals("DB_RECIPE.ProductNum")){
                nodes.add(node);
            }
        }
        return nodes;
    }
}
